﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlimDX.D3DCompiler;
using SlimDX;
using SlimDX.Direct3D11;
using SlimDX.DXGI;
using Apparat.ShaderManagement;

namespace Apparat.Renderables
{
  public class GridMesh : Renderable
  {
    SlimDX.Direct3D11.Buffer vertexBuffer;
    DataStream vertices;

    int numVertices = 0;
    int stride;

    float stepSize;

    public GridMesh(int witdh, int height, float stepSize)
    {
      int numVerticesWidth = witdh + 1;
      int numVerticesHeight = height + 1;

      this.stepSize = stepSize;

      numVertices = numVerticesWidth * numVerticesHeight;

      stride = 12;
      int sizeInBytes = stride * numVertices;
      vertices = new DataStream(sizeInBytes, true, true);

      float posX, posY;
      float startX = -witdh * stepSize / 2.0f;
      float startY = height * stepSize / 2.0f;

      for (int y = 0; y < numVerticesHeight; y++)
      {
        for (int x = 0; x < numVerticesWidth; x++)
        {
          posX = startX + x * stepSize;
          posY = startY - y * stepSize;

          vertices.Write(new Vector3(posX, posY, 0));
        }
      }

      vertices.Position = 0;

      // create the vertex buffer
      vertexBuffer = new SlimDX.Direct3D11.Buffer(DeviceManager.Instance.device, vertices, sizeInBytes, ResourceUsage.Default, BindFlags.VertexBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
    }

    EffectWrapperTransformEffect ew = ShaderManager.Instance.transformEffect;

    public override void Render()
    {
      Matrix ViewPerspective = CameraManager.Instance.ViewPerspective;
      Matrix WorldViewPerspective = this.transform * ViewPerspective;
      ew.tmat.SetMatrix(WorldViewPerspective);

      // configure the Input Assembler portion of the pipeline with the vertex data
      DeviceManager.Instance.context.InputAssembler.InputLayout = ew.layout;
      DeviceManager.Instance.context.InputAssembler.PrimitiveTopology = PrimitiveTopology.PointList;
      DeviceManager.Instance.context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertexBuffer, stride, 0));

      ew.technique = ew.effect.GetTechniqueByName("Render");

      EffectTechniqueDescription techDesc;
      techDesc = ew.technique.Description;

      for (int p = 0; p < techDesc.PassCount; ++p)
      {
        ew.technique.GetPassByIndex(p).Apply(DeviceManager.Instance.context);
        DeviceManager.Instance.context.Draw(numVertices, 0);
      }
    }

    public override void Dispose()
    {
    }

    public override Matrix Transform
    {
      get
      {
        return this.transform;
      }
      set
      {
        this.transform = value;
      }
    }
  }
}
